msg_tool\scripts\kirikiri\image/
tlg.rs1use crate::ext::io::*;
3use crate::scripts::base::*;
4use crate::types::*;
5use crate::utils::img::*;
6use anyhow::Result;
7use libtlg_rs::*;
8use std::io::{Read, Seek};
9
10#[derive(Debug)]
11pub struct TlgImageBuilder {}
13
14impl TlgImageBuilder {
15 pub const fn new() -> Self {
17 TlgImageBuilder {}
18 }
19}
20
21impl ScriptBuilder for TlgImageBuilder {
22 fn default_encoding(&self) -> Encoding {
23 Encoding::Cp932
24 }
25
26 fn build_script(
27 &self,
28 data: Vec<u8>,
29 _filename: &str,
30 _encoding: Encoding,
31 _archive_encoding: Encoding,
32 config: &ExtraConfig,
33 _archive: Option<&Box<dyn Script>>,
34 ) -> Result<Box<dyn Script>> {
35 Ok(Box::new(TlgImage::new(MemReader::new(data), config)?))
36 }
37
38 fn extensions(&self) -> &'static [&'static str] {
39 &["tlg", "tlg5", "tlg6"]
40 }
41
42 fn script_type(&self) -> &'static ScriptType {
43 &ScriptType::KirikiriTlg
44 }
45
46 fn is_image(&self) -> bool {
47 true
48 }
49
50 fn is_this_format(&self, _filename: &str, buf: &[u8], buf_len: usize) -> Option<u8> {
51 if buf_len >= 11 {
52 if is_valid_tlg(buf) {
53 return Some(255);
54 }
55 }
56 None
57 }
58
59 fn can_create_image_file(&self) -> bool {
60 true
61 }
62
63 fn create_image_file<'a>(
64 &'a self,
65 mut data: ImageData,
66 writer: Box<dyn WriteSeek + 'a>,
67 _options: &ExtraConfig,
68 ) -> Result<()> {
69 if data.depth != 8 {
70 return Err(anyhow::anyhow!("Unsupported image depth: {}", data.depth));
71 }
72 let color_type = match data.color_type {
73 ImageColorType::Bgr => TlgColorType::Bgr24,
74 ImageColorType::Bgra => TlgColorType::Bgra32,
75 ImageColorType::Grayscale => TlgColorType::Grayscale8,
76 ImageColorType::Rgb => {
77 convert_rgb_to_bgr(&mut data)?;
78 TlgColorType::Bgr24
79 }
80 ImageColorType::Rgba => {
81 convert_rgba_to_bgra(&mut data)?;
82 TlgColorType::Bgra32
83 }
84 };
85 let tlg = Tlg {
86 width: data.width,
87 height: data.height,
88 color: color_type,
89 data: data.data,
90 tags: Default::default(),
91 version: 5, };
93 save_tlg(&tlg, writer)?;
94 Ok(())
95 }
96}
97
98#[derive(Debug)]
99pub struct TlgImage {
101 data: Tlg,
102}
103
104impl TlgImage {
105 pub fn new<T: Read + Seek>(data: T, _config: &ExtraConfig) -> Result<Self> {
110 let tlg = load_tlg(data)?;
111 Ok(TlgImage { data: tlg })
112 }
113}
114
115impl Script for TlgImage {
116 fn default_output_script_type(&self) -> OutputScriptType {
117 OutputScriptType::Json
118 }
119
120 fn default_format_type(&self) -> FormatOptions {
121 FormatOptions::None
122 }
123
124 fn is_image(&self) -> bool {
125 true
126 }
127
128 fn export_image(&self) -> Result<ImageData> {
129 Ok(ImageData {
130 width: self.data.width,
131 height: self.data.height,
132 color_type: match self.data.color {
133 TlgColorType::Bgr24 => ImageColorType::Bgr,
134 TlgColorType::Bgra32 => ImageColorType::Bgra,
135 TlgColorType::Grayscale8 => ImageColorType::Grayscale,
136 },
137 depth: 8,
138 data: self.data.data.clone(),
139 })
140 }
141
142 fn import_image<'a>(
143 &'a self,
144 mut data: ImageData,
145 file: Box<dyn WriteSeek + 'a>,
146 ) -> Result<()> {
147 if data.depth != 8 {
148 return Err(anyhow::anyhow!("Unsupported image depth: {}", data.depth));
149 }
150 let color_type = match data.color_type {
151 ImageColorType::Bgr => TlgColorType::Bgr24,
152 ImageColorType::Bgra => TlgColorType::Bgra32,
153 ImageColorType::Grayscale => TlgColorType::Grayscale8,
154 ImageColorType::Rgb => {
155 convert_rgb_to_bgr(&mut data)?;
156 TlgColorType::Bgr24
157 }
158 ImageColorType::Rgba => {
159 convert_rgba_to_bgra(&mut data)?;
160 TlgColorType::Bgra32
161 }
162 };
163 let tlg = Tlg {
164 width: data.width,
165 height: data.height,
166 color: color_type,
167 data: data.data,
168 tags: self.data.tags.clone(),
169 version: 5, };
171 save_tlg(&tlg, file)?;
172 Ok(())
173 }
174}